package com.nexgo.payment.util;

import android.util.Xml;
import com.nexgo.data.XMLData;
import com.nexgo.data.Xmlfield;
import com.nexgo.data.entity.mapper.EntityDataMapper;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;

import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;


/**
 * Created by wzp on 2018/1/24.
 */

public class XmlUtils {

    private static Logger mLog = LoggerFactory.getLogger(EntityDataMapper.class.getSimpleName());
    private static final String xmlBOCOM = "bocomPay";
    private static final String xmlHEAD = "head";
    private static final String xmlBODY = "body";
    private static final String endHead = "mcht_id";
    private static final String xmlDeclare = "<?xml version='1.0' encoding='utf-8' standalone='no' ?>";
    public static String writeXmlSerial(Map<String, String> map ){
        XmlSerializer serializer = Xml.newSerializer();
        StringWriter writer = new StringWriter();
        try{
            serializer.setOutput(writer);
            serializer.startDocument("utf-8", false);
            serializer.startTag(null, xmlBOCOM);
            serializer.startTag(null, xmlHEAD);
                for (Map.Entry<String, String> m :map.entrySet())  {
                    mLog.debug("key :{} ,value : {}" , m.getKey(),m.getValue());
                    serializer.startTag(null, m.getKey());
                    serializer.text(m.getValue());
                    serializer.endTag(null, m.getKey());
                    if(endHead.equals(m.getKey())){  //head 结束 body开始
                        serializer.endTag(null, xmlHEAD);
                        serializer.startTag(null, xmlBODY);
                    }

                }
            serializer.endTag(null, xmlBODY);
            serializer.endTag(null, xmlBOCOM);
            serializer.endDocument();
        }
        catch(Exception e)
        {
            throw new RuntimeException(e);
        }
        return writer.toString();
    }

    public static XMLData Parser(String xmlStr ) throws XmlPullParserException, IOException {
        Map<String, String> xmlMap = new HashMap<>();
        XmlPullParser parser = Xml.newPullParser();
        mLog.debug("xmlStr = {}",xmlStr);
//        ByteArrayInputStream tInputStringStream ;
//        tInputStringStream = new ByteArrayInputStream(xmlStr.getBytes());
//        parser.setInput(tInputStringStream, "UTF-8");

        parser.setInput(new StringReader(xmlStr));
        int event = parser.getEventType();

        while (event != XmlPullParser.END_DOCUMENT) {
            switch (event) {
                case XmlPullParser.START_DOCUMENT:
                    break;
                case XmlPullParser.START_TAG:
                    mLog.debug("getName {}", parser.getName());
                    if(xmlBOCOM.equals(parser.getName())||
                            xmlHEAD.equals(parser.getName()) ||
                            xmlBODY.equals(parser.getName())){
                        break;
                    }
                    /*if(parser.nextText() != null)*/ {
                        xmlMap.put(parser.getName(), parser.nextText());
                    }
                    break;
                case XmlPullParser.END_TAG:
                    break;
            }
            event = parser.next();
            mLog.debug("event {}", event);
        }

        return  ParseMapToXMLData(xmlMap);

    }



    //组XML字符串
    public static String formXML(Object obj){

        Map<String, String> xmlMap = new LinkedHashMap<>();
        List<Field> fieldList = new ArrayList<>();
        Field[] fields = obj.getClass().getDeclaredFields();


        for (Field f : fields) {
            if (f.getAnnotation(Xmlfield.class) != null) {
                fieldList.add(f);
                mLog.debug("变量名字 ：{}" ,f.getName());
            }
        }
        Collections.sort(fieldList, (Field s1, Field s2) -> {
            Xmlfield field1 = s1.getAnnotation(Xmlfield.class);
            Xmlfield field2 = s2.getAnnotation(Xmlfield.class);
            mLog.debug("Xmlfield1 ：{} Xmlfield2:{}" ,field1.fieldIndex(),field2.fieldIndex());
            return field1.fieldIndex() - field2.fieldIndex();
        });
        for(int i=0;i<fieldList.size();i++)
        {
            mLog.debug("变量名字 after sort：{}" ,fieldList.get(i).getName());
        }
        Object value = null; // 取变量的值
        for (Field f:fieldList) {
            try {
                f.setAccessible(true);
                value = f.get(obj);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            if (value != null) {
                mLog.debug("key : {}\nvalue :{}" , f.getName(),value.toString());
                xmlMap.put(f.getName(), (String) value);
            }
        }

        mLog.debug("XML hashmap size : {}" , xmlMap.size());
        String xmlString = writeXmlSerial(xmlMap);
        return xmlString.substring(xmlDeclare.length(),xmlString.length());
    }

    public static XMLData ParseMapToXMLData (Map<String, String> map){
        XMLData mXMLData = new XMLData();
        Class<?> clazz = mXMLData.getClass();
        int count = 0;
        java.lang.reflect.Field[] fields = clazz.getDeclaredFields();
        for(java.lang.reflect.Field f :fields) {
            try {
                if(f.isAnnotationPresent(Xmlfield.class)) {
                    for (Map.Entry<String, String> m : map.entrySet()) {
                        if(m.getKey().equals(f.getName())){
                            f.setAccessible(true);
                            mLog.debug("map.key:{} map.value :{}", m.getKey(), m.getValue());
                            if(m.getValue() != null) {
                                f.set(mXMLData, m.getValue());
                            }
                            count++;
                        }
                    }
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        if (count == 0){
            return  null;
        }
        return mXMLData;
    }
}
